﻿using Newtonsoft.Json;
using System;
using XieCan.AspMVC.Extensions;

namespace XieCan.AspMVC
{
    /// <summary>
    /// 操作结果类
    /// </summary>
    /// <typeparam name="T">操作结果的数据类型</typeparam>
    public sealed class OperateResult<T> : XieCanBase
    {
        private OperateResult()
        {
        }

        /// <summary>
        /// 操作是否成功
        /// </summary>
        [JsonProperty(PropertyName = "state")]
        public bool Success { get; private set; } = false;

        /// <summary>
        /// 操作失败的详情
        /// </summary>
        [JsonIgnore]
        public Exception Error { get; private set; }

        /// <summary>
        /// 操作失败的关键词
        /// </summary>
        [JsonIgnore]
        public string Key { get; set; }

        /// <summary>
        /// 操作失败的原因
        /// </summary>
        [JsonProperty(PropertyName = "message")]
        public string Message => Error?.Message;

        /// <summary>
        /// 操作成功返回的数据
        /// </summary>
        [JsonProperty(PropertyName = "data")]
        public T Data { get; private set; } = default;

        /// <summary>
        /// 操作成功
        /// </summary>
        /// <param name="data">返回数据</param>
        /// <returns></returns>
        public static OperateResult<T> Succeeded(T data) => new OperateResult<T>()
        {
            Success = true,
            Data = data
        };

        /// <summary>
        /// 操作失败
        /// </summary>
        /// <param name="message">失败原因</param>
        /// <param name="key">失败标识</param>
        /// <returns></returns>
        public static OperateResult<T> Failed(string message, string key = "") => new OperateResult<T>()
        {
            Success = false,
            Data = default,
            Key = key,
            Error = new Exception(message: message)
        };

        /// <summary>
        /// 操作异常
        /// </summary>
        /// <param name="exception">内部异常</param>
        /// <param name="key">失败标识</param>
        /// <returns></returns>
        public static OperateResult<T> Failed(Exception exception, string key = "") => new OperateResult<T>()
        {
            Success = false,
            Data = default,
            Key = key,
            Error = exception.DepthException()
        };
    }
}
